import * as Cesium from 'cesium'
import { Base64toBlob, MaskPopup, RandomlyNum } from '@/utils/UtilFn'
import { useEarthGroup } from './EarthViewerGroup'
import { coverCoordinate } from './earthFn'
import type { PositionResult } from '@/type/utils';
import { useDrawGraphical } from './DrawGraphical'
import type { DrawAssistPointType } from '@/type/EditType';
import type { DrawDataType, BaseMerType } from '@/type/UseDraw';

export class useDrawMain {
    // 图层
    viewer: Cesium.Viewer;
    // 自定义组
    group: useEarthGroup;
    // 专门绘制图形的类
    DrawGraphical: useDrawGraphical;
    // 地图的方法
    EarthBindHandle: Cesium.ScreenSpaceEventHandler;
    // 绘制图形的类型
    GraphicalType: string;
    // 正在绘制的实体对象
    drawPolygonObj: BaseMerType | null = null;
    // 正在绘制图形的相关数据
    drawPolygonData: DrawDataType | { position: any[] };
    // 绘制用于跟随鼠标提示的小点
    MovePointObj: Cesium.Entity | unknown;
    // 绘制图形时暂存的经纬度数据
    LonLatArray: number[][] = new Array(0);
    // 动态绘制图层左击事件
    DrawLeftMouseEvent: Function | null = null;
    // 动态绘制图层右击事件/结束事件
    DrawRightMouseEvent: Function | null = null;

    /**
     * @param view 必传 地图的图层
     * @returns 
     */
    constructor(view: Cesium.Viewer) {
        if (!view) {
            throw new Error("请传入地图的图层")
        }
        this.viewer = view;
        this.group = new useEarthGroup(this.viewer);

        this.DrawGraphical = new useDrawGraphical(this.group, this.viewer);
        this.EarthBindEvent()

        this.GraphicalType = "";
        this.drawPolygonData = {
            position: []
        }

        return this;
    }
    /**
     * 绘制图形
     * @param type 要绘制图形的类型
     * @returns 实体对象/实体数据
     */
    useDraw(type: string) {
        
        if (!type) return false;
        if (this.drawPolygonObj) {
            MaskPopup("请右击结束")
            return false;
        }
        // 创建移动小圆球
        this.drawMovePoint()
        // 重新定义绘制图形的类型
        this.GraphicalType = type;
        return this.ByTypeDrawLayer(type)
    }
    /**
     * 根据类型绘制不同的图形
     * @param type 需要绘制图形的类型
     * @returns 
     */
    ByTypeDrawLayer(type: string) {
        let obj = null;
        
        obj = this.DrawGraphical.useMain(type);

        obj?.entity && (this.drawPolygonObj = obj.entity);
        obj && (this.drawPolygonData = obj.result);

        return obj;
    }
    // 动态根据类型绘制图形
    trendsDrawGrapByType(type: string, position: PositionResult) {
        let obj = null;
        switch (type) {
            case "POINT":
                obj = this.EditdrawPoint(position);
                break;
            case "LINE":
                obj = this.EditDrawLine(position)
                break;
            case "POLYGON":
                obj = this.EditDrawPolygon(position)
                break;
            case "PLANE":
                obj = this.EditDrawPlane(position)
                break;
            case "CIRCLE":
                obj = this.EditDrawCirCle(position)
                break;
            case "Label":
                obj = this.EditDrawTextLabel(position)
                break;
            case "LabelAndPoint":
                obj = this.EditDrawTextPoint(position)
                break;
            case "TERENTS_CIRCLE":
                obj = this.EditDrawWaterCircle(position)
                break;
            case "PATH":
                obj = this.EditDrawPath(position)
                break;
            case "LabelAndBill":
                obj = this.EditDrawTextbill(position)
                break;
            case "ELLIPSE":
                obj = this.EditDrawEllipseCircle(position)
                break;
            case "CYLINDER":
                obj = this.EditDrawCylinder(position)
                break;
            case "RIPPLE_ELLIPSE":
                obj = this.EditDrawRipple(position)
                break;
            case "INDUATION_POLYGON":
                obj = this.EditDrawInduate(position)
                break;
            case "LINE_Super":
                obj = this.EditDrawLineSuper(position)
                break;
            case "MODEL":
                obj = this.EditDrawModel(position)
                break;
            default:
                MaskPopup("此类型无法绘制")
                break;
        }
        return obj;
    }
    // 修改点
    EditdrawPoint(LonLatData: PositionResult) {
        let { lon, lat } = LonLatData;
        if (!this.drawPolygonObj) return;
        this.drawPolygonObj.position = Cesium.Cartesian3.fromDegrees(lon, lat);
        this.drawPolygonData.position = [lon, lat]
    }
    // 修改线
    EditDrawLine(LonLatData: PositionResult) {
        let { lon, lat } = LonLatData;
        if (!this.drawPolygonObj) return;
        this.LonLatArray.push([lon, lat])
        this.drawPolygonObj.polyline.positions = this.LonLatArray.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1]));
        this.drawPolygonData.position = this.LonLatArray
    }
    // 修改面
    EditDrawPolygon(LonLatData: PositionResult) {
        let { lon, lat } = LonLatData;
        if (!this.drawPolygonObj) return;
        this.LonLatArray.push([lon, lat])
        this.drawPolygonObj.position = Cesium.Cartesian3.fromDegrees(this.LonLatArray[0][0], this.LonLatArray[0][1]);
        this.drawPolygonObj.polygon.hierarchy = { positions: this.LonLatArray.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1])) };
        this.drawPolygonData.position = this.LonLatArray
    }

    // 修改抛物线位置
    EditDrawLineSuper(LonLatData: PositionResult) {
        let { lon, lat } = LonLatData;
        if (!this.drawPolygonObj) return;
        let text = "原点";
        if (this.LonLatArray.length > 0) {
            text = "扩散点";
        }
        // 根据放置经纬度容器的长度定义id
        // 此代码必须放在经纬度容器前面，在容器长度位变时定义
        let id = "AssistId" + this.LonLatArray.length;

        this.LonLatArray.push([lon, lat])

        this.drawAssistPoint({
            id: id,
            position: [lon, lat],
            text: text
        })
        this.drawPolygonData.position = this.LonLatArray
    }
    // 抛物线绘制结束后需要执行的函数
    EditDrawLineSuperEnd() {
        // 如果当前绘制的图形不是抛物线类型，直接退出
        if (this.GraphicalType != "LINE_Super") return false;
        let self = this;
        let len = this.LonLatArray.length;
        for (let i = 0; i < len; i++) {
            self.group?.removeGroupEntityById("AssistId" + i);
        }
        this.DrawGraphical.useMain(this.GraphicalType, this.drawPolygonData)
        return true;
    }
    // 修改模型的位置
    EditDrawModel(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改平面
    EditDrawPlane(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改圆
    EditDrawCirCle(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改文字标签
    EditDrawTextLabel(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改文字标签
    EditDrawTextbill(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改文字点
    EditDrawTextPoint(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改水波纹圆
    EditDrawWaterCircle(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改绘制的路径图形  
    EditDrawPath(LonLatData: PositionResult) {
        this.EditDrawLine(LonLatData)
    }
    // 修改绘制的电弧圆
    EditDrawEllipseCircle(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 修改圆柱体
    EditDrawCylinder(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 绘制波纹雷达
    EditDrawRipple(LonLatData: PositionResult) {
        // 直接调用修改点的逻辑
        this.EditdrawPoint(LonLatData)
    }
    // 为模拟的淹没效果绘制路线
    EditDrawInduate(LonLatData: PositionResult) {
        // 直接调用修改面的逻辑
        this.EditDrawPolygon(LonLatData)
    }
    /**
     * 为地图绑定方法
     * @returns 
     */
    private EarthBindEvent() {
        if (!this.viewer) return;
        let self = this;

        self.EarthBindHandle = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);
        
        // 添加右击方法
        self.EarthBindHandle.setInputAction((event: any) => {
            
            if (self.drawPolygonObj) {
                // 当绘制抛物线结束时执行的方法
                self.EditDrawLineSuperEnd();
                // 右击结束绘制，情况对象和数组
                self.LonLatArray = []
                self.GraphicalType = "";
                self.drawPolygonObj = null;
                self.MovePointObj instanceof Cesium.Entity && self.viewer?.entities.remove(self.MovePointObj)

                // 执行此回调方法
                self.DrawRightMouseEvent instanceof Function && self.DrawRightMouseEvent(event, self.drawPolygonObj, self.drawPolygonData)
            }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
         
        // 添加左击方法
        self.EarthBindHandle.setInputAction((event: any) => {
            if (self.drawPolygonObj) {
                // 屏幕坐标转经纬度
                let jw = coverCoordinate(self.viewer, event.position)

                self.trendsDrawGrapByType(self.GraphicalType, jw)

                // 执行此回调方法
                self.DrawLeftMouseEvent instanceof Function && self.DrawLeftMouseEvent(event, self.drawPolygonObj)
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

        // 添加鼠标移动事件
        self.EarthBindHandle.setInputAction((event: any) => {
            // 当符合指定的条件后执行相关逻辑
            if (self.drawPolygonObj && self.MovePointObj) {
                // 获取经纬度
                let jw = coverCoordinate(self.viewer, event.endPosition)
                // 修改提示点的位置
                self.MovePointObj.position = Cesium.Cartesian3.fromDegrees(jw!.lon, jw!.lat)
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
        
    }
    // 绘制移动时的提示点
    drawMovePoint() {
        this.group?.removeGroupEntityById("movePoint");
        
        this.MovePointObj = this.group?.addEntity({
            id: "movePoint",
            name: "移动的点",
            position: Cesium.Cartesian3.fromDegrees(0, 0, 0),
            point: {
                pixelSize: 6,
                color: Cesium.Color.WHITE,
                outlineColor: Cesium.Color.fromCssColorString("#1e9ffc").withAlpha(0.6),
                outlineWidth: 3
            }
        })
    }
    // 绘制图形时的辅助点
    drawAssistPoint(item: DrawAssistPointType) {
        if (!item || !item.id) return false;
        this.group.removeGroupEntityById(item.id);
        this.group.addEntity({
            id: item.id,
            name: "辅助标签",
            position: Cesium.Cartesian3.fromDegrees(item.position[0], item.position[1]),
            point: {
                pixelSize: 6,
                color: Cesium.Color.fromCssColorString("#fff"),
                outlineColor: Cesium.Color.fromCssColorString("#1e9ffc").withAlpha(0.6),
                outlineWidth: 3
            },
            label: {
                text: item.text,
                pixelOffset: Cesium.Cartesian2.fromElements(0, 15),
                fillColor: Cesium.Color.fromCssColorString("#fff"),
                font: `14px 微软雅黑`,
            }
        })

        return true;
    }
    /**
     * 截屏
     */
    ScreenShotCurrent() {
        let self = this;
        // 不写会导出为黑图
        self.viewer.render()
        let canvas = self.viewer.scene.canvas;
        let image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        let blob = Base64toBlob(image);
        return Promise.resolve({ image, blob })
    }
    /**
     * 更换图层,更换图层会将原来组内所有的实体全部删除
     * @param view 
     * @returns 
     */
    setViewer(view: Cesium.Viewer) {
        if (!view) return false;
        this.viewer = view;
        this.group.setViewer(view)
    }
    /**
     * 根据条件追踪绘制的对象
     * @param entity 对象实体或对象id
     */
    TrackGraphic(entity: string | Cesium.Entity) {
        if (entity instanceof Cesium.Entity) {
            this.viewer.zoomTo(entity)
        } else {
            let e = this.viewer.entities.getById(entity);
            this.viewer.zoomTo(e).then((res: any) => { });
        }
    }
    /**
     * 移动视角
     * @param position 对象实体或对象id
     * @param duration 间隔时间 默认：1
     */
    MoveCameraEye(position: number[], duration?: number) {
        this.viewer.camera.flyTo({
            duration: duration || 1,
            destination: Cesium.Cartesian3.fromDegrees(position[0], position[1], (position[3] || 30000))
        })
    }
    /**
     * 获取组对象
     * @returns 
     */
    getGroup() {
        return this.group;
    }
    /**
     * 获取地图对象
     * @returns 
     */
    getViewer() {
        return this.viewer;
    }
    /**
     * 销毁方法
     */
    destroy() {
        // 销毁方法
        if (!this.EarthBindHandle.isDestroyed()) {
            this.EarthBindHandle.destroy()
            this.EarthBindHandle = null;
        }
        // 地图对象置空
        this.viewer = null;
    }
}